import Koa from 'koa';
import Router from '@koa/router';
import bodyParser from 'koa-bodyparser';
import cors from '@koa/cors';
import koaBody from 'koa-body';
import koaStatic from 'koa-static';
import { Context } from 'koa';
import { resolve } from 'path';
import fs from 'fs-extra';
const PUBLIC_DIR = resolve(__dirname, 'public');
const TEMP_DIR = resolve(__dirname, 'temp');
const app = new Koa();
const router = new Router();


const init = async () => {
  if (!await fs.pathExists(PUBLIC_DIR)) {
    fs.mkdirs(PUBLIC_DIR);
  }
  if (!await fs.pathExists(TEMP_DIR)) {
    fs.mkdirs(TEMP_DIR);
  }
}

init()
app.use(koaStatic(PUBLIC_DIR)); //将public下的代码静态化
app.use(koaBody({
  multipart: true, // 支持文件上传
  formidable: {
    maxFileSize: 3000 * 1024 * 1024, // 设置上传文件大小的限制，3G
  },
}));
router.get('/verify/:filename', async (ctx) => {
  const filename = ctx.params.filename;
  const filePath = resolve(PUBLIC_DIR, filename);
  const existFile = await fs.pathExists(filePath);
  if (existFile) {
    // 已经上传合并
    ctx.body = {
      code: 0,
      message: '成功',
      uploadDone: true,
      uploadList: []
    }
  } else {
    const tempDir = resolve(TEMP_DIR, filename);
    const exist = await fs.pathExists(tempDir);
    let uploadList: any[] = [];
    if (exist) {
      // 部分已经上传
      uploadList = await fs.readdir(tempDir);
      uploadList = await Promise.all(uploadList.map(async (filename: string) => {
        const stat = await fs.stat(resolve(tempDir, filename));
        return {
          chunkName: filename,
          size: stat.size //现在的文件大写 100M  30M
        }
      }));
    }
    ctx.body = {
      code: 0,
      message: '成功',
      uploadDone: false,
      uploadList
    };
  }


});


const merge = (readerFile: string, writerFile: string, start: number) => {
  return new Promise<void>((resolve) => {
    // 创建可读流
    const reader = fs.createReadStream(readerFile);
    // 创建写入流
    const writer = fs.createWriteStream(writerFile, { start: Number(start), flags: 'a' });
    reader.pipe(writer);

    writer.on('error', (err) => {
      console.error(`错误信息：${err}`);
      writer.close();
    });

    writer.on('finish', () => {
      resolve()
      writer.end();
      writer.close();
      // 删除文件
      fs.unlink(readerFile)
    });
  })

}



router.get('/merge/:filename', async (ctx) => {
  const filename = ctx.params.filename;
  const publicDir = resolve(PUBLIC_DIR);
  const filePath = resolve(PUBLIC_DIR, filename); // 文件存储的位置
  const chunksDir = resolve(TEMP_DIR, filename); // 获取切片的临时目录
  const chunkFiles = await fs.readdir(chunksDir); // 获取切片的临时文件
  console.log(chunkFiles.length);
  // 文件不存在创建
  if (!await fs.pathExists(publicDir)) {
    await fs.mkdirs(publicDir);
  }
  //按文件名升序排列
  chunkFiles.sort((a, b) => Number(a.split('-')[1]) - Number(b.split('-')[1]));
  let offset = 0

  await Promise.all(chunkFiles.map(async (filename, index) => {
    if (index > 0) {
      const stat = await fs.stat(resolve(chunksDir, filename))
      offset += stat.size
    }
    return merge(resolve(chunksDir, filename), filePath, offset)
  }))
  // 上传完成删除切片目录
  await fs.rmdir(chunksDir);
  ctx.body = {
    code: 0,
    message: '成功',
  };

});



router.post('/upload/:filename/:chunkName/:start', async (ctx: Context) => {
  const { filename, chunkName, start } = ctx.params;
  // 获取上传的文件
  const file: any = ctx.request.files?.file;
  // 获取上传文件的临时路径
  const chunk_dir = resolve(TEMP_DIR, filename);
  const exist = await fs.pathExists(chunk_dir);
  // 文件不存在创建
  if (!exist) {
    await fs.mkdirs(chunk_dir);
  }
  const targetPath = resolve(chunk_dir, chunkName);
  // 创建可读流
  const reader = fs.createReadStream(file.filepath);
  // 创建写入流
  const writer = fs.createWriteStream(targetPath, { start: Number(start), flags: 'a' });
  reader.pipe(writer);


  const writeFileAsync = () => {
    return new Promise((resolve, reject) => {
      writer.on('error', (err) => {
        console.error(`错误信息：${err}`);
        writer.close()
      });
    
      writer.on('finish', () => {
        console.log('writeFileAsync写入操作已完成');
        resolve(true)
        writer.end();
        writer.close()
    
      });
    });
  };
 
  await writeFileAsync()
  ctx.body = {
    code: 0,
    message: '文件上传成功',
  };

});


router.post('/upload/record', async (ctx: Context) => {
  // 获取上传的文件
  const file: any = ctx.request.files?.file;
  // 获取上传文件的临时路径
  const chunk_dir = resolve(PUBLIC_DIR, 'record');
  const exist = await fs.pathExists(chunk_dir);
  // 文件不存在创建
  if (!exist) {
    await fs.mkdirs(chunk_dir);
  }
  const filename = new Date().getTime() + ''
  const targetPath = resolve(chunk_dir, filename);
  // 创建可读流
  const reader = fs.createReadStream(file.filepath);
  // 创建写入流
  const writer = fs.createWriteStream(targetPath);
  reader.pipe(writer);

  writer.on('error', (err) => {
    console.error(`错误信息：${err}`);
    writer.close()
  });

  writer.on('finish', () => {
    console.log('record写入操作已完成');
    writer.end();
    writer.close()

  });
  ctx.body = {
    code: 0,
    url: `http://localhost:3000/record/${filename}`,
    message: '文件上传成功',
  };

});

app.use(cors());
app.use(bodyParser());
app.use(router.routes());
app.use(router.allowedMethods());

app.listen(3000, () => {
  console.log('Server running on port 3000');
});
